% Chakram is a subproject of Hexena - Haskell Executable Analyser
% License:			GPL-3
% Maintainer:		Montez Fitzpatrick
% Stability:		Experimental
% Portability:		GHC
% Module:			Hexena.Codec.Parser.PECOFF

This module represents the parsing function for the PE/COFF File

\begin{code}
module Hexena.Codec.Parser.PECOFF (parsePE) where

import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString.Lazy.Char8 as L8

import Data.Binary.Get
import Data.Int (Int64)

import Hexena.Data.PECOFF (PE(..))
import Hexena.Data.MzHeader (MzHeader(..))
import Hexena.Data.FileHeader (FileHeader(..))
import Hexena.Data.SectionHeader (SectionHeader(..))

import Hexena.Codec.Parser.MzHeader (parseMzHeader)
import Hexena.Codec.Parser.DOSStub (parseDosStub)
import Hexena.Codec.Parser.PEHeader (parsePeHeader)
import Hexena.Codec.Parser.SectionHeader (parseSecHeader)
import Hexena.Codec.Parser.ParseRawSections (parseRawSections)

parsePE = do
	pe_mzheader <- parseMzHeader

	let offSetToPE = fromIntegral $ get lfanew pe_mzheader :: Int64
	currentOffSet <- bytesRead

	pe_dosstub <- parseDosStub (offSetToPE - currentOffSet)
	pe_peheader <- parsePeHeader

	-- setting the number of sections we need to recusively get
	let secNum = fromIntegral $ get (numOfSections . fileHdr) pe_peheader :: Int
	
	pe_secHeader <- parseSecHeader secNum

	pe_secRaw <- parseRawSections $ get sectionList pe_secHeader

	pe_rest <- getRemainingLazyByteString

	return $ PE pe_mzheader pe_dosstub pe_peheader pe_secHeader pe_secRaw pe_rest
\end{code}

\begin{spec}
-- TESTING

input = "..\\..\\..\\hexena-test\\test\\simple.exe"

peFile :: FilePath -> IO PE
peFile f =
	L.readFile f >>= \fh -> return $ runGet parsePe fh

\end{spec}
